home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / TIFF / TIFFSIFT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  7.9 KB  |  308 lines

  1.  
  2. /* Copyright (c) Mark J. Kilgard, 1997.  */
  3.  
  4. /* This program is freely distributable without licensing fees 
  5.    and is provided without guarantee or warrantee expressed or 
  6.    implied. This program is -not- in the public domain. */
  7.  
  8. /* This program uses 3D texture coordinates to introduce
  9.    "sifting" effects to warp a static mesh of textured
  10.    geometry.  The third texture coordinate encodes a shifting
  11.    quantity through the mesh.  By updating the texture matrix,
  12.    the texture coordinates can be shifted based on this
  13.    third texture coordinate.  You'll notice the image seems
  14.    to have local vortexes scattered over the image that
  15.    warp the image.  While the texture coordinates look dynamic,
  16.    they are indeed quite static (frozen in a display list) and
  17.    it is just the texture matrix that is changing to shift
  18.    the final 2D texture coordinates. */
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <math.h>       /* for cos(), sin(), and sqrt() */
  24. #include <GL/glut.h>
  25. #include <tiffio.h>     /* Sam Leffler's libtiff library. */
  26.  
  27. TIFFRGBAImage img;
  28. uint32 *raster;
  29. uint32 *texture;
  30. tsize_t npixels;
  31.  
  32. float tick = 0;
  33. float size = 0.6;
  34. int set_timeout = 0;
  35. int visible = 0;
  36. int sifting = 1;
  37. int interval = 100;
  38.  
  39. int hasABGR = 0;
  40. int doubleBuffer = 1;
  41. char *filename = NULL;
  42.  
  43. int tw, th;
  44.  
  45. void
  46. animate(int value)
  47. {
  48.   if (visible) {
  49.     if (sifting) {
  50.       if (value) {
  51.         if (sifting) {
  52.           tick += 4 * (interval / 100.0);
  53.         }
  54.       }
  55.       glutPostRedisplay();
  56.       set_timeout = 1;
  57.     }
  58.   }
  59. }
  60.  
  61. /* Setup display list with "frozen" 3D texture coordinates. */
  62. void
  63. generateTexturedSurface(void)
  64. {
  65.   static GLfloat data[8] =
  66.   {0, 1, 0, -1, 0, -1, 0, 1};
  67.   int i, j;
  68.  
  69. #define COLS 6
  70. #define ROWS 6
  71. #define TILE_TEX_W (1.0/COLS)
  72. #define TILE_TEX_H (1.0/ROWS)
  73.  
  74.   glNewList(1, GL_COMPILE);
  75.   glTranslatef(-COLS / 2.0 + .5, -ROWS / 2.0 + .5, 0);
  76.   for (j = 0; j < ROWS; j++) {
  77.     glBegin(GL_QUAD_STRIP);
  78.     for (i = 0; i < COLS; i++) {
  79.       glTexCoord3f(i * TILE_TEX_W, j * TILE_TEX_H, data[(i + j) % 8]);
  80.       glVertex2f(i - .5, j - .5);
  81.       glTexCoord3f(i * TILE_TEX_W, (j + 1) * TILE_TEX_H, data[(i + j + 1) % 8]);
  82.       glVertex2f(i - .5, j + .5);
  83.     }
  84. #if 1
  85.     glTexCoord3f((i + 1) * TILE_TEX_W, j * TILE_TEX_H, data[(i + j) % 8]);
  86.     glVertex2f(i + .5, j - .5);
  87.     glTexCoord3f((i + 1) * TILE_TEX_W, (j + 1) * TILE_TEX_H, data[(i + j + 1) % 8]);
  88.     glVertex2f(i + .5, j + .5);
  89.     glEnd();
  90. #endif
  91.   }
  92.   glEndList();
  93. }
  94.  
  95. /* Construct an identity matrix except that the third coordinate
  96.    can be used to "sift" the X and Y coordinates. */
  97. void
  98. makeSift(GLfloat m[16], float xsift, float ysift)
  99. {
  100.   m[0 + 4 * 0] = 1;
  101.   m[0 + 4 * 1] = 0;
  102.   m[0 + 4 * 2] = xsift;
  103.   m[0 + 4 * 3] = 0;
  104.  
  105.   m[1 + 4 * 0] = 0;
  106.   m[1 + 4 * 1] = 1;
  107.   m[1 + 4 * 2] = ysift;
  108.   m[1 + 4 * 3] = 0;
  109.  
  110.   m[2 + 4 * 0] = 0;
  111.   m[2 + 4 * 1] = 0;
  112.   m[2 + 4 * 2] = 1;
  113.   m[2 + 4 * 3] = 0;
  114.  
  115.   m[3 + 4 * 0] = 0;
  116.   m[3 + 4 * 1] = 0;
  117.   m[3 + 4 * 2] = 0;
  118.   m[3 + 4 * 3] = 1;
  119. }
  120.  
  121. void
  122. redraw(void)
  123. {
  124.   int begin, end, elapsed;
  125.   GLfloat matrix[16];
  126.  
  127.   if (set_timeout) {
  128.     begin = glutGet(GLUT_ELAPSED_TIME);
  129.   }
  130.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  131.   glPushMatrix();
  132.  
  133.   glScalef(size, size, size);
  134.  
  135.   glMatrixMode(GL_TEXTURE);
  136.   makeSift(matrix, 0.02 * cos(tick / 15.0), 0.02 * sin(tick / 15.0));
  137.   glLoadMatrixf(matrix);
  138.   glMatrixMode(GL_MODELVIEW);
  139.  
  140.   glCallList(1);
  141.  
  142.   glPopMatrix();
  143.   if (doubleBuffer) {
  144.     glutSwapBuffers();
  145.   } else {
  146.     glFlush();
  147.   }
  148.   if (set_timeout) {
  149.     set_timeout = 0;
  150.     end = glutGet(GLUT_ELAPSED_TIME);
  151.     elapsed = end - begin;
  152.     if (elapsed > interval) {
  153.       glutTimerFunc(0, animate, 1);
  154.     } else {
  155.       glutTimerFunc(interval - elapsed, animate, 1);
  156.     }
  157.   }
  158. }
  159.  
  160. void
  161. visibility(int state)
  162. {
  163.   if (state == GLUT_VISIBLE) {
  164.     visible = 1;
  165.     animate(0);
  166.   } else {
  167.     visible = 0;
  168.   }
  169. }
  170.  
  171. int
  172. main(int argc, char **argv)
  173. {
  174.   TIFF *tif;
  175.   char emsg[1024];
  176.   int i;
  177.  
  178.   glutInit(&argc, argv);
  179.   for (i = 1; i < argc; i++) {
  180.     if (!strcmp(argv[i], "-sb")) {
  181.       doubleBuffer = 0;
  182.     } else {
  183.       filename = argv[i];
  184.     }
  185.   }
  186.   if (filename == NULL) {
  187.     fprintf(stderr, "usage: textiff [GLUT-options] [-sb] TIFF-file\n");
  188.     exit(1);
  189.   }
  190.   tif = TIFFOpen(filename, "r");
  191.   if (tif == NULL) {
  192.     fprintf(stderr, "Problem showing %s\n", filename);
  193.     exit(1);
  194.   }
  195.   if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
  196.     npixels = (tsize_t) (img.width * img.height);
  197.     raster = (uint32 *) _TIFFmalloc(npixels * (tsize_t) sizeof(uint32));
  198.     if (raster != NULL) {
  199.       if (TIFFRGBAImageGet(&img, raster, img.width, img.height) == 0) {
  200.         TIFFError(filename, emsg);
  201.         exit(1);
  202.       }
  203.     }
  204.     TIFFRGBAImageEnd(&img);
  205.   } else {
  206.     TIFFError(filename, emsg);
  207.     exit(1);
  208.   }
  209.   if (doubleBuffer) {
  210.     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
  211.   } else {
  212.     glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
  213.   }
  214.   glutInitWindowSize((int) img.width, (int) img.height);
  215.   glutCreateWindow("tiffsift");
  216.   glutDisplayFunc(redraw);
  217.   glutVisibilityFunc(visibility);
  218. #ifdef GL_EXT_abgr
  219.   if (glutExtensionSupported("GL_EXT_abgr"))
  220.     hasABGR = 1;
  221. #else
  222.   hasABGR = 0;
  223. #endif
  224.   /* If cannot directly display ABGR format, we need to reverse the component
  225.      ordering in each pixel. :-( */
  226.   if (!hasABGR) {
  227.     int i;
  228.  
  229.     for (i = 0; i < npixels; i++) {
  230.       register unsigned char *cp = (unsigned char *) &raster[i];
  231.       int t;
  232.  
  233.       t = cp[3];
  234.       cp[3] = cp[0];
  235.       cp[0] = t;
  236.       t = cp[2];
  237.       cp[2] = cp[1];
  238.       cp[1] = t;
  239.     }
  240.   }
  241.   /* OpenGL's default unpack (and pack) alignment is 4.  In the case of the
  242.      data returned by libtiff which is already aligned on 32-bit boundaries,
  243.      setting the pack to 1 isn't strictly necessary. */
  244.   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  245.   gluOrtho2D(-1, 1, -1, 1);
  246.  
  247.   /* Linear sampling within a mipmap level. */
  248.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  249.     GL_LINEAR_MIPMAP_NEAREST);
  250.  
  251.   glEnable(GL_TEXTURE_2D);
  252.  
  253.   /* A TIFF file could be any size; OpenGL textures are allowed to have a
  254.      width and height that is a power of two (32, 64, 128, etc.). To maximize
  255.      the use of available texture memory, we scale the image to gluScaleImage
  256.      to the next larger power of 2 width or height dimension (not exceeding
  257.      512, don't want to use too much texture memory!).  This rescaling can
  258.      result in a bit of image bluring because of the resampling done by
  259.      gluScaleImage.  An alternative would be to change the texture coordinates 
  260.      to only use a portion texture area. */
  261.  
  262.   tw = 1 << (int) ceil(log(img.width) / log(2.0));
  263.   th = 1 << (int) ceil(log(img.height) / log(2.0));
  264.   if (tw > 512)
  265.     tw = 512;
  266.   if (th > 512)
  267.     th = 512;
  268.   texture = (uint32 *) malloc(sizeof(GLubyte) * 4 * tw * th);
  269.  
  270. #ifdef GL_EXT_abgr
  271. #define APPROPRIATE_FORMAT (hasABGR ? GL_ABGR_EXT : GL_RGBA)
  272. #else
  273. #define APPROPRIATE_FORMAT GL_RGBA
  274. #endif
  275.  
  276.   gluScaleImage(APPROPRIATE_FORMAT,
  277.     (GLsizei) img.width, (GLsizei) img.height, GL_UNSIGNED_BYTE, raster,
  278.     tw, th, GL_UNSIGNED_BYTE, texture);
  279.   _TIFFfree(raster);
  280.  
  281.   /* Build mipmaps for the texture image.  Since we are not scaling the image
  282.      (we easily could by calling glScalef), creating mipmaps is not really
  283.      useful, but it is done just to show how easily creating mipmaps is. */
  284.   gluBuild2DMipmaps(GL_TEXTURE_2D, 4, tw, th,
  285.     APPROPRIATE_FORMAT, GL_UNSIGNED_BYTE,
  286.     texture);
  287.  
  288.   /* Use a gray background so TIFF images with black backgrounds will
  289.      show against textiff's background. */
  290.   glClearColor(0.2, 0.2, 0.2, 1.0);
  291.  
  292.   glMatrixMode(GL_PROJECTION);
  293.   glLoadIdentity();
  294.   gluPerspective( /* field of view in degree */ 40.0,
  295.   /* aspect ratio */ 1.0,
  296.     /* Z near */ 1.0, /* Z far */ 70.0);
  297.   glMatrixMode(GL_MODELVIEW);
  298.   glLoadIdentity();
  299.   gluLookAt(0.0, 0.0, 5.0,  /* eye is at (0,0,30) */
  300.     0.0, 0.0, 0.0,      /* center is at (0,0,0) */
  301.     0.0, 1.0, 0.);      /* up is in positive Y direction */
  302.  
  303.   generateTexturedSurface();
  304.  
  305.   glutMainLoop();
  306.   return 0;             /* ANSI C requires main to return int. */
  307. }
  308.